﻿#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "common/config_manager.h"
#include "widgets/TestInterface/testwidget.h"
#include "widgets/HardwareSetup/hardwarewidget.h"
#include "widgets/TestTemplate/testtemplatewidget.h"
#include "widgets/TableManager/parameterbrowserwidget.h"
#include "model/temperaturehumiditysensor.h"

#include <QtDebug>
#include <QDir>
#include <QSettings>
#include <QFont>
#include <QButtonGroup>

const int RESIZE_MARGIN = 15;

/**
 * @brief MainWindow::MainWindow
 * @details 构造主窗口并初始化核心组件。
 * @param parent 父窗口指针，为空时表示创建顶层窗口。
 */
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    , m_leftSidebarBtnGroup(new QButtonGroup(this))
    , m_tempHumSensor(new TemperatureHumiditySensor)
{
    ui->setupUi(this);
    initIconFont();
    initUI();
    connect(m_tempHumSensor, &TemperatureHumiditySensor::sig_updataData, this, &MainWindow::slot_updataData);
    m_tempHumSensor->start();
}

/**
 * @brief MainWindow::~MainWindow
 * @details 释放主窗口持有的资源并安全关闭线程。
 */
MainWindow::~MainWindow()
{
    Utils::saveWindowState(isFullScreen());
    if (isFullScreen())
        showNormal();
    Utils::saveGeometry(this->geometry());
    delete ui;
    if (m_tempHumSensor) {
        m_tempHumSensor->quit();
        if (!m_tempHumSensor->wait(500)) { // 等待2秒
            m_tempHumSensor->terminate();
            // m_tempHumSensor->wait(500);
        }
        delete m_tempHumSensor;
        m_tempHumSensor = nullptr;
    }
}

/**
 * @brief MainWindow::mousePressEvent
 * @details 处理鼠标按下事件以启动拖动或缩放。
 * @param event 鼠标事件，提供按钮与位置等信息。
 */
void MainWindow::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_resizeEdges = getResizeEdges(event->pos(), RESIZE_MARGIN);
        if (m_resizeEdges != 0) {
            m_isResizing = true;
            m_resizeStartPosition = event->globalPos();
        } else {
            // 假设标题栏在顶部约100像素的高度
            if (event->y() < 100) {
                m_isDragging = true;
                m_dragStartPosition = event->globalPos() - frameGeometry().topLeft();
            }
        }
    }
}

/**
 * @brief MainWindow::mouseMoveEvent
 * @details 根据鼠标移动更新窗口拖动或缩放状态。
 * @param event 鼠标移动事件，包含当前位置。
 */
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isResizing) {
        // --- 窗口缩放逻辑 ---
        QRect newGeometry = geometry();
        QPoint delta = event->globalPos() - m_resizeStartPosition;

        if (m_resizeEdges.testFlag(Qt::TopEdge)) {
            newGeometry.setTop(newGeometry.top() + delta.y());
        }
        if (m_resizeEdges.testFlag(Qt::BottomEdge)) {
            newGeometry.setBottom(newGeometry.bottom() + delta.y());
        }
        if (m_resizeEdges.testFlag(Qt::LeftEdge)) {
            newGeometry.setLeft(newGeometry.left() + delta.x());
        }
        if (m_resizeEdges.testFlag(Qt::RightEdge)) {
            newGeometry.setRight(newGeometry.right() + delta.x());
        }

        // 保证窗口有最小尺寸
        if (newGeometry.width() < minimumWidth())
            newGeometry.setWidth(minimumWidth());
        if (newGeometry.height() < minimumHeight())
            newGeometry.setHeight(minimumHeight());

        setGeometry(newGeometry);
        m_resizeStartPosition = event->globalPos();

    } else if (m_isDragging) {
        // --- 窗口拖动逻辑 ---
        move(event->globalPos() - m_dragStartPosition);
    } else {
        // --- 更新鼠标光标形状 ---
        updateCursorShape(event->pos());
    }
    event->accept();
}

/**
 * @brief MainWindow::mouseReleaseEvent
 * @details 在鼠标释放时结束拖动或缩放操作。
 * @param event 鼠标释放事件，指示释放的按钮。
 */
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_isDragging = false;
        m_isResizing = false;
        m_resizeEdges = 0;
        // 释放后恢复默认光标
        setCursor(Qt::ArrowCursor);
        event->accept();
    }
}
/**
 * @brief MainWindow::getResizeEdges
 * @details 判断鼠标位置对应的可缩放边缘。
 * @param pos 鼠标相对于窗口的坐标。
 * @param margin 激活缩放的边缘宽度阈值。
 * @return 返回组合后的边缘标志，用于表示可缩放方向。
 */
Qt::Edges MainWindow::getResizeEdges(const QPoint &pos, int margin)
{
    Qt::Edges edges;
    if (pos.x() < margin)
        edges |= Qt::LeftEdge;
    if (pos.x() > width() - margin)
        edges |= Qt::RightEdge;
    if (pos.y() < margin)
        edges |= Qt::TopEdge;
    if (pos.y() > height() - margin)
        edges |= Qt::BottomEdge;
    return edges;
}

/**
 * @brief MainWindow::updateCursorShape
 * @details 根据鼠标所在边缘更新光标形态。
 * @param pos 鼠标在窗口中的位置。
 */
void MainWindow::updateCursorShape(const QPoint &pos)
{
    Qt::Edges edges = getResizeEdges(pos, RESIZE_MARGIN);
    if (edges == (Qt::TopEdge | Qt::LeftEdge) || edges == (Qt::BottomEdge | Qt::RightEdge)) {
        setCursor(Qt::SizeFDiagCursor);
    } else if (edges == (Qt::TopEdge | Qt::RightEdge) || edges == (Qt::BottomEdge | Qt::LeftEdge)) {
        setCursor(Qt::SizeBDiagCursor);
    } else if (edges.testFlag(Qt::TopEdge) || edges.testFlag(Qt::BottomEdge)) {
        setCursor(Qt::SizeVerCursor);
    } else if (edges.testFlag(Qt::LeftEdge) || edges.testFlag(Qt::RightEdge)) {
        setCursor(Qt::SizeHorCursor);
    } else {
        setCursor(Qt::ArrowCursor);
    }
}

/**
 * @brief MainWindow::setSysSheet
 * @details 根据索引应用对应的样式表。
 * @param index 样式表的索引值。
 */
void MainWindow::setSysSheet(int index)
{
    //    QString qssPath = QDir::currentPath();
    //    if (index == 0) {
    //        qssPath += "/qss/mainwindow.qss";
    //        return;
    //    } else {
    //        qssPath += "/qrc/styles.qss";
    //    }

    QFile file;
    file.setFileName(":/blacktheme/blackstyles.qss");
    if (file.open(QFile::ReadOnly)) {
        QString styleSheet = tr(file.readAll());
        qApp->setStyleSheet(styleSheet);
        file.close();
    } else
        qDebug() << file.errorString();
}

/**
 * @brief MainWindow::initUI
 * @details 初始化窗口界面元素并绑定信号槽。
 */
void MainWindow::initUI()
{
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
    setMouseTracking(true);
    ui->centralwidget->setObjectName("mainBackground");
    setSysSheet(1);

    setGeometry(Utils::loadGeometry());
    if (!Utils::loadWindowState()) {
        ui->restoreButton->setText(QChar(0xea68));
        showNormal();
    } else {
        ui->restoreButton->setText(QChar(0xea69));
        showFullScreen();
    }

    m_leftSidebarBtnGroup->addButton(ui->radioButton_ht_rs, 0);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_ht_cs, 1);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_tt, 2);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_coe, 3);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_ls, 4);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_cal, 5);
    m_leftSidebarBtnGroup->addButton(ui->radioButton_test, 6);

    ui->stackedWidget->insertWidget(0, new HardwareWidget(HardwareTemplateType::RS));
    ui->stackedWidget->insertWidget(1, new HardwareWidget(HardwareTemplateType::CS));
    ui->stackedWidget->insertWidget(2, new TestTemplateWidget());
    ui->stackedWidget->insertWidget(3, new ParameterBrowserWidget());
    ui->stackedWidget->insertWidget(4, new TestWidget(TestProcessStage::LevelScanning));
    ui->stackedWidget->insertWidget(5, new TestWidget(TestProcessStage::Calibration));
    ui->stackedWidget->insertWidget(6, new TestWidget(TestProcessStage::Testing));

    connect(m_leftSidebarBtnGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &MainWindow::slot_groupButtonClicked);
    connect(qobject_cast<TestWidget *>(ui->stackedWidget->widget(4)), &TestWidget::sig_updateDeviceStatus, this, &MainWindow::slot_updateDeviceStatus);
    connect(qobject_cast<TestWidget *>(ui->stackedWidget->widget(5)), &TestWidget::sig_updateDeviceStatus, this, &MainWindow::slot_updateDeviceStatus);
    connect(qobject_cast<TestWidget *>(ui->stackedWidget->widget(6)), &TestWidget::sig_updateDeviceStatus, this, &MainWindow::slot_updateDeviceStatus);

    ui->stackedWidget->setCurrentIndex(ui->stackedWidget->count() - 1);
    ui->radioButton_test->setChecked(true);
}

/**
 * @brief MainWindow::initIconFont
 * @details 加载图标字体并应用到工具按钮。
 */
void MainWindow::initIconFont()
{
    QString fontFile(":/iconfont.ttf");
    if (!QFile(fontFile).exists())
        return;

    int fontId = QFontDatabase::addApplicationFont(fontFile);
    QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
    QFont fontIcon = QFont(fontName);
    fontIcon.setPixelSize(25);

    ui->helpButton->setFont(fontIcon);
    ui->minimizeButton->setFont(fontIcon);
    ui->restoreButton->setFont(fontIcon);
    ui->closeButton->setFont(fontIcon);

    ui->helpButton->setText(QChar(0xe6a3));
    ui->minimizeButton->setText(QChar(0xea6a));
    ui->restoreButton->setText(QChar(0xea68));
    ui->closeButton->setText(QChar(0xe97d));
}
/**
 * @brief MainWindow::on_comboBox_currentIndexChanged
 * @details 响应样式下拉框切换以应用新样式。
 * @param index 当前选中的下拉项索引。
 */
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
    setSysSheet(index);
}

/**
 * @brief MainWindow::on_closeButton_clicked
 * @details 关闭按钮点击事件，执行窗口关闭。
 */
void MainWindow::on_closeButton_clicked()
{
    close();
}

/**
 * @brief MainWindow::on_restoreButton_clicked
 * @details 还原按钮点击事件，在全屏与窗口模式间切换。
 */
void MainWindow::on_restoreButton_clicked()
{
    if (isFullScreen()) {
        showNormal();
        ui->restoreButton->setText(QChar(0xea68));
    } else {
        ui->restoreButton->setText(QChar(0xea69));
        showFullScreen();
    }
}

/**
 * @brief MainWindow::on_minimizeButton_clicked
 * @details 最小化按钮点击事件，将窗口最小化。
 */
void MainWindow::on_minimizeButton_clicked()
{
    showMinimized();
}

/**
 * @brief MainWindow::slot_groupButtonClicked
 * @details 切换左侧分组按钮对应的页面。
 * @param id 按钮组分配的索引号。
 */
void MainWindow::slot_groupButtonClicked(int id)
{
    if (id > 5)
        ui->stackedWidget->setCurrentIndex(ui->stackedWidget->count() - 1);
    else
        ui->stackedWidget->setCurrentIndex(id);
}

/**
 * @brief MainWindow::slot_updateDeviceStatus
 * @details 更新设备状态指示灯显示。
 * @param st 设备测量状态，包含角色与连接状态。
 */
void MainWindow::slot_updateDeviceStatus(const DeviceMeasureStatus &st)
{
    QLabel *label = nullptr;
    switch (st.role) {
    case DeviceRole::SignalGenerator:
        label = ui->label_Gen;
        break;
    case DeviceRole::Amplifier:
        label = ui->label_Pa;
        break;
    case DeviceRole::PowerMeterForward:
        label = ui->label_Pfwd;
        break;
    case DeviceRole::PowerMeterReverse:
        label = ui->label_Prev;
        break;
    case DeviceRole::PowerMeterMonitor:
        label = ui->label_MonitDevice;
        break;
    case DeviceRole::Receiver:
        label = ui->label_ScanDevice;
        break;
    default:
        break;
    }
    if (!label)
        return;
    switch (st.stat) {
    case DeviceStatus::Connected:
        label->setStyleSheet("border-image: url(:/blacktheme/icons/st_on.png);");
        break;
    case DeviceStatus::Abnormal:
        label->setStyleSheet("border-image: url(:/blacktheme/icons/st_err.png);");
        break;
    case DeviceStatus::DisConnect:
        DeviceStatus ds = static_cast<DeviceStatus>(label->property("status").toUInt());
        if (ds != DeviceStatus::Abnormal)
            label->setStyleSheet("border-image: url(:/blacktheme/icons/st_off.png);");
        break;
    }
    label->setProperty("status", QVariant(st.stat));
}

/**
 * @brief MainWindow::slot_updataData
 * @details 展示最新的温湿度数据。
 * @param temp 温度数值，单位摄氏度。
 * @param hum 湿度值，以百分比表示。
 */
void MainWindow::slot_updataData(double temp, double hum)
{
    if (m_language.isEmpty())
        m_language = Utils::getAppLanguage();
    ui->label_temp->setText(QString("<html><head/><body><p style= 'font-size: 19px;'>%1: <span style= 'color:#01c4e3;'>%2</span></p></body></html>").arg(tr("Temp")).arg(temp));
    QString chText = QString("<html><head/><body><p style='text-align: center;font-size: 19px;'>%1: <span style='color:#01c4e3;'>%2%</span></p></body></html>").arg(tr("Humidity")).arg(hum);
    QString enText = QString("<html><head/><body><p style= 'font-size: 19px;'>Humidity: <span style= 'color:#01c4e3;'>%1%</span></p></body></html>").arg(hum);
    (m_language == "en_US") ? ui->label_humidity->setText(enText) : ui->label_humidity->setText(chText);
}

/**
 * @brief MainWindow::on_helpButton_clicked
 * @details 帮助按钮点击事件，弹出功能菜单。
 */
void MainWindow::on_helpButton_clicked()
{
    QMenu menu(this);
    QAction *actLog = menu.addAction(tr("View Log"));
    connect(actLog, &QAction::triggered, this, &MainWindow::onViewLog);

    QMenu *langMenu = menu.addMenu(tr("Language"));
    QActionGroup *langGroup = new QActionGroup(this);
    langGroup->setExclusive(true);

    QAction *actChinese = langMenu->addAction(tr("Chinese"));
    actChinese->setCheckable(true);
    actChinese->setData("zh_CN");
    langGroup->addAction(actChinese);

    QAction *actEnglish = langMenu->addAction(tr("English"));
    actEnglish->setCheckable(true);
    actEnglish->setData("en_US");
    langGroup->addAction(actEnglish);
    (Utils::getAppLanguage() == "en_US") ? actEnglish->setChecked(true) : actChinese->setChecked(true);
    connect(langGroup, &QActionGroup::triggered, this, &MainWindow::onLanguageChanged);

    QAction *actAbout = menu.addAction(tr("About"));
    connect(actAbout, &QAction::triggered, this, &MainWindow::onShowVersion);

    QPoint globalPos = ui->helpButton->mapToGlobal(QPoint(0, ui->helpButton->height()));
    menu.exec(globalPos);
    update();
}

/**
 * @brief MainWindow::onViewLog
 * @details 打开最新生成的日志文件。
 * @param checked QAction 的选中状态，未使用。
 */
void MainWindow::onViewLog(bool checked)
{
    Q_UNUSED(checked) // 防止未使用参数警告

    QString logDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/logs";
    QDir().mkpath(logDir);

    // 查找最新的日志文件
    QDir logDirectory(logDir);
    QFileInfoList logFiles = logDirectory.entryInfoList(
        QStringList() << "*.log" /*<< "*.txt"*/,
        QDir::Files | QDir::NoDotAndDotDot, QDir::Time);
    QDateTime latestDateTime = logFiles.first().lastModified();
    QFileInfo latestFile = logFiles.first();

    for (const QFileInfo &fileInfo : logFiles) {
        if (fileInfo.lastModified() > latestDateTime) {
            latestDateTime = fileInfo.lastModified();
            latestFile = fileInfo;
        }
    }

    QString logFilePath = latestFile.absoluteFilePath();
    QDesktopServices::openUrl(QUrl::fromLocalFile(logFilePath));
}

/**
 * @brief MainWindow::onShowVersion
 * @details 显示关于对话框，展示版本与环境信息。
 * @param checked QAction 的选中状态，未使用。
 */
void MainWindow::onShowVersion(bool checked)
{
    Q_UNUSED(checked)

    QString appName = QApplication::applicationName();
    if (appName.isEmpty())
        appName = "EMC Custom Software";

    QString appVersion = QApplication::applicationVersion();
    if (appVersion.isEmpty())
        appVersion = APP_VERSION;

    QString versionInfo = QString(tr(
                                      "<html><head/><body>"
                                      "<p style='margin: 3;'>%1</p>"
                                      "<p style='margin-top: 10; margin-bottom: 0; margin-left: 3'>Version: %2</p>"
                                      "<p style='margin: 3;'>Build Date: %3</p>"
                                      "<p style='margin: 3;'>Architecture: %4</p>"
                                      "<p style='margin: 3;'>OS: %5</p>"
                                      "<p style='margin-top: 10; margin-bottom: 0;margin-left: 3'>Copyright <span style=\"font-family: 'iconfont'; vertical-align: middle;\">&#xe61b;</span> 2022-2023 The Halox Company Ltd.</p>"
                                      "<p style='margin: 3;'>www.halox.cn</p>"
                                      "</body></html>"))
                              .arg(appName)
                              .arg(appVersion)
                              .arg(QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss"))
                              .arg(
#ifdef _WIN64
                                  "x64"
#else
                                  "x86"
#endif
                                  )
                              //            .arg(QSysInfo::prettyProductName());
                              .arg("Windows 11");

    QMessageBox::about(this, tr("About"), versionInfo);
}

/**
 * @brief MainWindow::onLanguageChanged
 * @details 处理语言切换请求并提示重启应用。
 * @param act 用户选择的语言动作，携带语言代码。
 */
void MainWindow::onLanguageChanged(QAction *act)
{
    Q_UNUSED(act)
    if (!act)
        return;

    Utils::setAppLanguage(act->data().toString());

    QString langName = act->text();
    QMessageBox::StandardButton reply = QMessageBox::question(
        this,
        tr("Language Change"),
        tr("Application needs to restart to apply changes.\n"
           "Do you want to restart now?"),
        QMessageBox::Yes | QMessageBox::No);

    if (reply == QMessageBox::Yes) {
        // QCoreApplication::processEvents();
        // QThread::msleep(100);

        QProcess::startDetached(qApp->applicationFilePath(), QStringList());
        QCoreApplication::quit();
    }
}
